#include<iostream>
using namespace std;
#include<list>

#if 0
// 虚函数表
// A::func
// A::test
class A
{
public:
    A()
        :m_iVal(0)
    {
        test();
    }

    virtual void func()
    {
        std::cout << m_iVal << ' ';
    }

    void test()
    {
        func();
    }

public:

    int m_iVal;

};

// 虚函数表
// B::func
// A::test
class B : public A
{
public:

    B()
        // :A()
    {
        test();
    }

    virtual void func();


};

void B::func()
{
    ++m_iVal;
    std::cout << m_iVal << ' ';

}

int main(int argc, char* argv[])
{

    A* p = new B;// new 的同时调用构造函数 初始化B的对象

    p->test();

    return 0;

}
#endif

#if 0
class A
{
public:
    virtual void f()
    {
        cout << "A::f()" << endl;
    }
};

class B : public A
{
    //public:
private:
    virtual void f()
    {
        cout << "B::f()" << endl;
    }
};

int main()
{
    B b;
    // b.f(); 
    A* pa = (A*)new B;
    pa->f();//正常访问不行，因为函数权限是私有的。 而通过虚表访问没有问题
    //子类函数为私有，但是多态仅仅是用子类函数的地址覆盖虚表，最终调用的位置不变，只是执行函数发生变化
}
#endif

#if 0
class A
{
public:
    void test(float a)
    {
        cout << a;
    }
};
class B :public A
{
public:
    void test(int b)
    {
        cout << b;
    }
};
void main()
{
    A* a = new A;
    B* b = new B;
    a = b;
    a->test(1.1);
    cout << "------------------" << endl;
    A* a1 = new B;
    a1->test(1);

}
#endif

///////////////////
///////////////////

#if 0
class B
{
public:
    // 不能
    // 原因：假设可以
    // 构造函数的入口地址也要放到虚表中，构造函数作用：就是在构造对象
    // 时，给对象中的各个非静态成员变量设置一个合适的初始值，包括将虚表的地址放到对象的前4个字节
    // 构造函数如果是虚函数，将来也要通过虚表进行调用，而构造函数中才是
    // 给对象前4个字节放入虚表地址，构造函数没有调用，对象前4个字节中
    // 就无法找到虚表的地址
    /*virtual*/ B()
    {}

    // 语法可以通过编译
    // 不能
    virtual inline void f1()
    {
        cout << "B::f1()" << endl;
    }

    // 不能
    // 假设可以，f2地址也要在虚表中存放
    // 将来调用时需要通过虚表来调用
    // 但是静态成员函数可以通过类名::静态成员函数名字()
    /*virtual*/ static void f2()
    {
        cout << "B::f2()" << endl;
    }

    virtual ~B()
    {
        cout << "B::~B()" << endl;
    }
};

class D : public B
{
public:
    virtual inline void f1()
    {
        cout << "D::f1()" << endl;
    }
};


void TestVirtual(B& b)
{
    b.f1();
    b.f2();
    B::f2();
}


int main()
{
    B b;
    D d;

    TestVirtual(b);
    TestVirtual(d);
    return 0;
}
#endif

#if 0
// 建议：在继承体系中，最好将基类的析构函数设置为虚函数
// 如果子类中涉及到资源管理时，尽可能将基类的析构函数设置为虚函数
// 以防止资源泄漏
class B
{
public:

    B()
    {
        cout << "B::B()" << endl;
    }

    void f1()
    {}

    virtual void f2()
    {}

    virtual ~B()
    {
        cout << "B::~B()" << endl;
    }
};

class D : public B
{
public:
    D()
    {
        cout << "D::D()" << endl;
        _p = new int[10];
    }

    ~D()
    {
        delete[] _p;
        _p = nullptr;
        cout << "D::~D()" << endl;
    }

    int* _p;
};


int g_a = 10;

int main()
{
    char* str = "hello";
    B* pb = new D;

    pb->f1();
    pb->f2();


    delete pb;


    return 0;
}
#endif

#if 0
class Tire
{
public:
    Tire()
    {}

    void func()
    {
        cout << "Tire::func()" << endl;
        cout << "Tire::func()" << endl;
        fun(10);
    }

protected:
    void fun(int a)
    {

    }
private:
    double _r;
    string _color;
    string _brand;
};


// 发动机
class Engine
{
protected:
    int  r;
    string _brand;
};

class Car
{
public:
    Car()
    {}

    void f()
    {
        _t[0].func();
    }

    virtual void drive() = 0;

protected:
    Tire _t[4];
    Engine _engine;
    // ...
};

class Benz : public Car
{
public:
    virtual void drive()
    {
        // ....
    }
};

class BMW : public Car
{
public:
    virtual void drive()
    {
        // ....
    }
};
#endif

///////////////////
///////////////////

#include <vector>

void TestList1()
{
    list<int> L1;
    list<int> L2(10, 5);

    vector<int> v{ 1,2,3,4,5 };
    
    list<int> L3(v.begin(), v.end());

    list<int> L4(L3);

    // C++11
    list<int> L5{ 1, 2, 3, 4, 5 };

    /////////////////////////////////////////
    // 链表遍历
    for (auto e : L2)
        cout << e << " ";
    cout << endl;

    // list<int>::iterator it = L3.begin();
    auto it = L3.begin();
    while (it != L3.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;

    auto rit = L4.rbegin();
    while (rit != L4.rend())
    {
        cout << *rit << " ";
        ++rit;
    }
    cout << endl;

    // 注意：list不能使用原生态指针，即Node*来遍历链表
    // 因为list没有提供获取头指针的方法
}

void TestList2()
{
    list<int> L{ 1, 2, 3, 4, 5 };
    cout << L.size() << endl;

    L.resize(10, 6);
    for (auto e : L)
        cout << e << " ";
    cout << endl;

    L.resize(20);
    for (auto e : L)
        cout << e << " ";
    cout << endl;

    L.resize(7);
    for (auto e : L)
        cout << e << " ";
    cout << endl;
}

void TestList3()
{
    list<int> L{ 1, 2, 3, 4, 5 };
    
    L.push_back(6);
    L.push_back(7);
    L.push_back(8);
    L.push_back(9);
    cout << L.size() << endl;
    cout << L.front() << endl;
   
    cout << L.back() << endl;

    L.pop_back();
    L.pop_back();
    for (auto e : L)
        cout << e << " ";
    cout << endl;

    L.push_front(0);
    for (auto e : L)
        cout << e << " ";
    cout << endl;

    L.pop_front();
    for (auto e : L)
        cout << e << " ";
    cout << endl;


   
    L.insert(L.begin(), 0); //插入一个元素

    auto pos = find(L.begin(), L.end(), 5);
    if (pos != L.end())
        L.insert(pos, 5, 8); // 插入5 个 8

    int array[] = { 10, 20, 30, 40, 50 };

    L.insert(L.end(), array, array + sizeof(array) / sizeof(array[0]));//在末尾插入一段区间
}

void TestList4()
{
    list<int> L{ 1, 2, 3, 4, 5 };
    L.push_back(6);
    L.push_back(7);
    L.push_back(8);
    L.push_back(9);

    L.erase(L.begin());
    L.erase(find(L.begin(), L.end(), 8));
    L.erase(L.begin(), L.end());    // 相当于clear();

    L.assign(10, 5);// 相当于Linux里面的打开文件并清除之前的内容，有可能底层空间会改变

    int array[] = { 10, 20, 30, 40, 50 };
    L.assign(array, array + sizeof(array) / sizeof(array[0]));
}

void TestList5()
{
    list<int> L{ 1, 2, 3, 4, 5, 1, 2, 3, 4, 5 ,1,1,1 };
    L.remove(1);//删除所有值为1的元素

    L.sort();

    L.unique(); //排序后才能去重

    L.reverse(); //逆置
}

bool IsEven(int data)//判断是否为偶数
{
    // 5的二进制：0000 0101
    //          0000 0001
    // return 0 == (data & 0x01);
    return 0 == data % 2;
}

void TestList6()
{
    list<int> L{ 1, 2, 3, 4, 5 };
    L.push_back(6);
    L.push_back(7);
    L.push_back(8);
    L.push_back(9);

    L.remove_if(IsEven);//删除所有偶数
}

void TestList7()//迭代器失效
{
    list<int> L{ 1, 2, 3, 4, 5 };
    L.push_back(6);
    L.push_back(7);
    L.push_back(8);
    L.push_back(9);

    auto it = L.begin();
    /*L.pop_front();
    while (it != L.end())
    {
    	cout << *it << " ";
    	++it;
    }*/

    //L.resize(0);
    //while (it != L.end())
    //{
    //	cout << *it << " ";
    //	++it;
    //}

    // L.assign(10, 5);
    //list<int> L1{ 10, 20, 30, 40, 50 };
    //L = L1;

    //while (it != L.end())
    //{
    //	cout << *it << " ";
    //	++it;
    //}

    while (it != L.end())
    {
         L.erase(it);
         ++it;
        it = L.erase(it);
    }
}

int main()
{
    //TestList1();
    //TestList2();
    //TestList3();
    //TestList4();
    //TestList5();
    //TestList6();
    TestList7();
    // 418
    return 0;
}

